`timescale 1ns/1ps
`include "code\source\P3\nco_psk.v"

module test_nco_psk;
initial begin
    $dumpfile("./release/test_nco_psk.vcd");
    $dumpvars(0, test_nco_psk);
end
// Generate clock
reg clk, clk2;
initial clk = 0;
always #1 clk = ~clk;

initial clk2 = 0;
always #100 clk2 = ~clk2;

// Input registers
reg reset, load, din, din_valid;
reg [31:0] fcw;
reg [31:0] phase_offset;


// Output wires
wire out_valid;
wire [11:0] out;

// TB Variable
wire [14:0] lut_addr;
wire [11:0] lut_data;
reg [11:0] lut_mem [0:32768];

initial begin
    $readmemb("D:/programming/verilog/Digital_Communication_SelfTest/code/test/P3/code_lut.txt", lut_mem);
end

assign lut_data = lut_mem[lut_addr];

// Tasks
task set_fcw(input [31:0] _fcw, input [31:0] _poff);
    begin
        $display("set_fcw: %d phase_offset: %d", _fcw, _poff);
        @(negedge clk);
        fcw = _fcw;
        phase_offset = _poff;
        load = 1;
        @(negedge clk);
        load = 0;
    end
endtask

initial begin
    reset = 1;
    load = 0;
    fcw = 0;
    phase_offset = 0;
    din = 0;
    din_valid = 0;
    @(negedge clk)
     reset = 0;
    repeat(2) @(posedge  clk);

    set_fcw(300000000, 1 << 31);

    din_valid = 1;
    repeat(10) begin
        @(posedge clk2);
        #0 din = ~din;
    end
    din_valid = 0;

    repeat(1000) @(posedge clk);
    // Exit the simulation
    $finish;
end

integer i = 1;

always@(negedge clk) begin
    if (out_valid) begin
        i <= i + 1;
        $display("%d: %b",i, out);;
    end
end

// Device under test (our adder)
nco_psk dut (.rst_n(~reset), .clk(clk), .load(load), .fcw(fcw), .phase_offset(phase_offset),  .out(out), .out_valid(out_valid), .din(din), .din_valid(din_valid), .lut_data(lut_data), .lut_addr(lut_addr));

endmodule
